#ifndef __MAIZE_RTOS_DEF_H
#define __MAIZE_RTOS_DEF_H

#include "mzconfig.h"

#ifdef __cplusplus
extern "C" {
#endif
typedef char                    mz_int8_t;
typedef short                   mz_int16_t;
typedef long                    mz_int32_t;

typedef unsigned char           mz_uint8_t;
typedef unsigned short          mz_uint16_t;
typedef unsigned long           mz_uint32_t;

typedef mz_uint32_t             mz_tick_t;
typedef mz_uint32_t             mz_base_t;

#define MZ_NULL                 (0)

#define MZ_FALSE                (0)
#define MZ_TRUE                 (1)

/* Compiler Related Definitions */
#if defined(__CC_ARM) || defined(__CLANG_ARM)           /* ARM Compiler */
#include <stdarg.h>
    #define SECTION(x)                  __attribute__((section(x)))
    #define MZ_UNUSED                   __attribute__((unused))
    #define MZ_USED                     __attribute__((used))
    #define ALIGN(n)                    __attribute__((aligned(n)))

    #define MZ_WEAK                     __attribute__((weak))
    #define mz_inline                   static __inline

#elif defined (__IAR_SYSTEMS_ICC__)     /* for IAR Compiler */
#include <stdarg.h>
    #define SECTION(x)                  @ x
    #define MZ_UNUSED
    #define MZ_USED                     __root
    #define PRAGMA(x)                   _Pragma(#x)
    #define ALIGN(n)                    PRAGMA(data_alignment=n)
    #define MZ_WEAK                     __weak
    #define mz_inline                   static inline

#elif defined (__GNUC__)                /* GNU GCC Compiler */
#ifdef MZ_USING_NEWLIB
#include <stdarg.h>
#else
/* the version of GNU GCC must be greater than 4.x */
typedef __builtin_va_list       __gnuc_va_list;
typedef __gnuc_va_list          va_list;
#define va_start(v,l)           __builtin_va_start(v,l)
#define va_end(v)               __builtin_va_end(v)
#define va_arg(v,l)             __builtin_va_arg(v,l)
#endif

#define SECTION(x)                  __attribute__((section(x)))
#define MZ_UNUSED                   __attribute__((unused))
#define MZ_USED                     __attribute__((used))
#define ALIGN(n)                    __attribute__((aligned(n)))
#define MZ_WEAK                     __attribute__((weak))
#define mz_inline                   static __inline
#elif defined (__ADSPBLACKFIN__)        /* for VisualDSP++ Compiler */
#include <stdarg.h>
    #define SECTION(x)                  __attribute__((section(x)))
    #define MZ_UNUSED                   __attribute__((unused))
    #define MZ_USED                     __attribute__((used))
    #define ALIGN(n)                    __attribute__((aligned(n)))
    #define MZ_WEAK                     __attribute__((weak))
    #define mz_inline                   static inline
#elif defined (_MSC_VER)
    #include <stdarg.h>
    #define SECTION(x)
    #define MZ_UNUSED
    #define MZ_USED
    #define ALIGN(n)                    __declspec(align(n))
    #define MZ_WEAK
    #define mz_inline                   static __inline
#elif defined (__TI_COMPILER_VERSION__)
    #include <stdarg.h>
    /* The way that TI compiler set section is different from other(at least
     * GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more
     * details. */
    #define SECTION(x)
    #define MZ_UNUSED
    #define MZ_USED
    #define PRAGMA(x)                   _Pragma(#x)
    #define ALIGN(n)
    #define MZ_WEAK
    #define mz_inline                   static inline
#else
    #error not supported tool chain
#endif

#define MZ_TIMER_MAX_CYCLE              0xffffffff

#define MZ_ALIGN(size, align)           (((size) + (align) - 1) & ~((align) - 1))

#define MZ_ALIGN_DOWN(size, align)      ((size) & ~((align) - 1))

/* List */
struct mz_list_node{
    struct mz_list_node* prev;
    struct mz_list_node* next;
};
typedef struct mz_list_node* mz_list_t;

/* Object */
struct mz_object{
    char name[MZ_NAME_MAX];

    mz_uint8_t type;
    mz_uint8_t flag;

    struct mz_list_node list;
};
typedef struct mz_object* mz_object_t;
typedef enum{
    MZ_OBJECT_THREAD,
    MZ_OBJECT_TIMER,
#if MZ_USE_MUTEX
    MZ_OBJECT_MUTEX,
#endif
    MZ_OBJECT_MAX
}mz_object_type_t;

/* Timer */
#define MZ_TIMER_DEACTIVATED                    0
#define MZ_TIMER_ACTIVATED                      1

#define MZ_TIMER_ONE_SHOT                       1
#define MZ_TIMER_PERIODIC                       -1
struct mz_timer{
    struct mz_object parent;

    void (*entry)(void* arg);
    void* arg;

    mz_tick_t cycle;
    mz_tick_t current_tick;
    mz_int32_t repeat;

    struct mz_list_node list;
};
typedef struct mz_timer* mz_timer_t;

/* Thread */
struct exception_stack_reg {
    mz_uint32_t r0;
    mz_uint32_t r1;
    mz_uint32_t r2;
    mz_uint32_t r3;
    mz_uint32_t r12;
    mz_uint32_t lr;
    mz_uint32_t pc;
    mz_uint32_t psr;
};
struct stack_reg{
    mz_uint32_t r4;
    mz_uint32_t r5;
    mz_uint32_t r6;
    mz_uint32_t r7;
    mz_uint32_t r8;
    mz_uint32_t r9;
    mz_uint32_t r10;
    mz_uint32_t r11;

    struct exception_stack_reg exception_stack_reg;
};
struct mz_thread{
    struct mz_object parent;

    void (*entry)(void* arg);
    void* arg;

    /* Thread built-in timer */
    struct mz_timer timer;

    mz_tick_t init_tick;
    mz_tick_t remaining_tick;

    mz_uint8_t init_priority;
    mz_uint8_t current_priority;

    void* stack_addr;
    mz_uint32_t stack_size;

    void* sp;

    struct mz_list_node list;
};
typedef struct mz_thread* mz_thread_t;

/* IPC */
#define MZ_IPC_FLAG_FIFO                            0
#define MZ_IPC_FLAG_PRIO                            1
struct mz_ipc{
    struct mz_object parent;

    struct mz_list_node suspend_list;
};
typedef struct mz_ipc* mz_ipc_t;

#if MZ_USE_MUTEX
struct mz_mutex{
    struct mz_ipc parent;

    mz_uint8_t value;

    struct mz_list_node suspend_list;
};
typedef struct mz_mutex* mz_mutex_t;
#endif

#ifdef __cplusplus
}
#endif
#endif